home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_300
/
307_01
/
comx.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-03-18
|
25KB
|
742 lines
/*
HEADER: ;
TITLE: PC com port driver;
VERSION: 1.0;
DESCRIPTION: "MS-DOS serial port device driver. Provides buffered
input and output to serial port with optional XON/XOFF
flow control through standard read/write requests or
interrupt 0x14.
Mixed memory model used. COMX.C compiled as small
model with explicitly declared far pointers. Front
end program coerces the linkage editor to produce a
tiny model executable.";
WARNINGS: "Microsoft specific. Startup code contained in
COMXFE.ASM does not initialize uninitialized static
variables to zero.";
KEYWORDS: Serial communications, device driver;
SYSTEM: MS-DOS v2 or later;
FILENAME: COMX.C;
SEE-ALSO: COMX, COMXFE.ASM, COMXBE.C;
AUTHORS: Hugh Daschbach;
COMPILERS: Microsoft v5.0,v5.1;
*/
/*----------------------------------------------------------------------*/
/* comx.c: MS-DOS driver for multiple communication devices (com1 - com4).
*/
#include "comx.h"
/* Instalation:
* This program is installed as an MS-DOS device driver by including
* the following entry in the CONFIG.SYS file:
* DEVICE = COMX.SYS xxx [xxx [xxx [xxx]]]
* where xxx is a com port address in hexadecimal (e.g. 3fa). At least
* one port is required. The driver will support as many as four.
*
* The communication devices are assumed to interrupt on either IRQ3 or
* IRQ4. More than one device can share the same interrupt line as
* each defined port is polled on every interrupt. Other versions of
* this driver support dedicated interrupt vectors, eliminating the
* polling operation at interrupt time. However, even with the polling
* overhead, the driver has been tested successfully at 9600 baud on a
* 4.77 Mhz 8088.
*/
/*----------------------------------------------------------------------*/
/* System Declarations */
/*----------------------------------------------------------------------*/
#pragma pack(1)
int inp(unsigned int);
int outp(unsigned int, int);
void _enable(void);
void _disable(void);
#pragma intrinsic(inp, outp, _enable, _disable)
/*----------------------------------------------------------------------*/
/* Local Data Declarations */
/*----------------------------------------------------------------------*/
typedef unsigned char uchar;
typedef unsigned short ushort;
/*----------------------------------------------------------------------*/
/* External Function Prototypes. */
/*----------------------------------------------------------------------*/
extern void int10(unsigned ax, unsigned bx);
/*----------------------------------------------------------------------*/
/* Local function prototypes */
/*----------------------------------------------------------------------*/
static void check_block(struct comport *chan);
static int com_int(void);
static char *define_lines(char far *cp);
extern void driver(struct rb far *rbp, int line_no);
static int eol(int c);
static void get_char(struct comport *chan);
static void hookvect(unsigned int intnum, struct isr_block *isr,
void (cdecl *handler)());
static int int14(ushort ax, ushort bx, ushort cx,
ushort dx, ushort ds, ushort es);
static int isspace(int c);
static int nop(int i);
static void put_char(struct comport *chan);
static void putc(int c);
static void puts(char *s);
static void putx(int i);
static void setspeed(struct comport *chan, int sti);
/*----------------------------------------------------------------------*/
/* Driver interface declarations */
/*----------------------------------------------------------------------*/
enum opcodes { /* Driver operation codes: */
INIT = 0, /* initialization */
MEDIA_CHECK, /* media check */
BUILD_BPB, /* build BIOS Parameter Block */
INPUT_IOCTL, /* input control string */
INPUT, /* read */
NON_DEST_INPUT, /* non destructive input */
INPUT_STATUS, /* input available status */
INPUT_FLUSH, /* flush input buffer */
OUTPUT, /* write */
OUTPUT_VERIFY, /* write with verify */
OUTPUT_STATUS, /* output busy status */
OUTPUT_FLUSH, /* flush output buffer */
OUTPUT_IOCTL, /* output control string */
DEVICE_OPEN, /* device open (removable media) */
DEVICE_CLOSE, /* device close (removable media) */
REMOVEABLE_MEDIA, /* more removable media */
GENERIC_IOCTL = 19, /* more ioctl */
GET_LOGICAL_DEVICE = 23, /* get logical device */
SET_LOGICAL_DEVICE = 24 /* set logical device */
};
/* Driver status indicators: */
#define DONE 0x0100 /* I/O done */
#define BUSY 0x0200 /* device busy */
#define ERROR 0x8000 /* I/O error */
enum errcodes { /* Driver error codes: */
WRITE_PROTECT, /* write protect violation */
UNKNOWN_UNIT, /* unknown unit */
NOT_READY, /* device non ready */
UNKNOWN_COMMAND, /* unknown command */
CRC_ERROR, /* CRC error */
BAD_STRUCT_LENGTH, /* bad drive request structure length */
SEEK_ERROR, /* seek error */
UNKNOWN_MEDIA, /* unknown media */
SECTOR_NOT_FOUND, /* sector not found */
PAPER_OUT, /* printer out of paper */
WRITE_FAULT, /* write fault */
READ_FAULT, /* read fault */
GENERAL_FAILURE, /* general failure */
RESV_D, /* reserved */
RESV_E, /* reserved */
INVALID_DISK_CHANGE /* invalid disk change */
};
typedef struct rb { /* I/O Request block */
uchar len; /* request block length */
uchar unit; /* unit code */
uchar op_code; /* operation code */
int status; /* status code */
char resv[8]; /* reserved */
union {
struct {
uchar count; /* unit count */
char far *end; /* end of resident module */
char far *bpbp; /* BPB array pointer */
uchar drive; /* drive number */
} init;
struct {
uchar media; /* media descriptor byte */
char far *buf; /* transfer buffer pointer */
int count; /* byte/sector count */
int sector; /* starting sector number */
char far *vol_id; /* volume idenitifier pointer */
} inout;
char ndi; /* non destructive input data byte */
} os; /* operation specific */
} rb;
/*----------------------------------------------------------------------*/
/* Interrupt service routine interface declaration */
/*----------------------------------------------------------------------*/
typedef struct isr_block { /* Interrupt Service Routine */
uchar push_es;
uchar push_ds;
uchar push_dx;
uchar push_cx;
uchar push_bx;
uchar push_ax;
ushort mov_ax_cs;
ushort mov_ds_ax;
uchar call;
ushort target;
ushort or_ax_ax;
uchar pop_ax;
uchar pop_bx;
uchar pop_cx;
uchar pop_dx;
uchar pop_ds;
uchar pop_es;
ushort jz_ip01;
uchar cs_prefix;
ushort jmp;
void (far **fnpp)(void);
uchar iret;
void (far *fnp)(void);
} isr_block;
/*----------------------------------------------------------------------*/
/* Hardware interface declarations */
/*----------------------------------------------------------------------*/
/* Line Status Register definition */
#define LSR_RDA 1 /* receive data available */
#define LSR_OR 2 /* overrun error */
#define LSR_PE 4 /* parity error */
#define LSR_FE 8 /* framing error */
#define LSR_BI 0x10 /* break interupt */
#define LSR_TBA 0x20 /* transmit holding buffer available */
#define LSR_TSRE 0x40 /* transmit shift buffer empty */
/* Modem Control Register definitions */
#define MCR_DTR 1 /* data terminal ready */
#define MCR_RTS 2 /* request to send */
#define MCR_OUT1 4 /* reset Hayes Smartmodem */
#define MCR_OUT2 8 /* enable Hayes Smartmodem interrupts */
#define MCR_LOOP 0x10 /* loop back test enable */
/* Interrupt Identification Register */
#de